﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SchoolManagerMVC.BusinessAbstract.Interfaces;
using SchoolManagerMVC.Web.Areas.Faculty.Controllers;
using SchoolManagerMVC.Web.Areas.Faculty.ViewModels;
using SchoolManagerMVC.Repository.EntityFramework;
using SchoolManagerMVC.Web.Models;
using System.Web.Security;
using SchoolManagerMVC.Tests.Helpers;
using System.Web.Mvc;

namespace SchoolManagerMVC.Tests.Controllers.FacultyArea
{
    //faculty
    [TestClass]
    public class HomeControllerTest
    {
        Mock<IRepository> _repoMock;
        Mock<IMembership> _repoMembership;

        HomeController controller;
        FacultyCreationViewModel facultyVM;
        FacultyMember facultyMember;

        [TestInitialize]
        public void setup()
        {
            _repoMock = new Mock<IRepository>();
            _repoMembership = new Mock<IMembership>();
            controller = new HomeController(_repoMock.Object, _repoMembership.Object);

            facultyMember = new FacultyMember()
            {
                FirstName = "Bob",
                LastName = "Knight",
                Age = 33,
                Salary = 0,
                UniqueID = Guid.NewGuid()
            };

            facultyVM = new FacultyCreationViewModel()
            {
                facultyMember = facultyMember,
                registerModel = new RegisterModel()
                {
                    UserName = "BOB",
                    Password = "Password",
                    ConfirmPassword = "Password",
                    Email = "bob@test.com"
                }
            };

            _repoMock.Setup(x => x.GetSingle<FacultyMember>(It.IsAny<Func<FacultyMember, bool>>())).Returns(facultyMember);
            _repoMembership.Setup(x => x.createUser(facultyVM.registerModel.UserName, facultyVM.registerModel.Password, facultyVM.registerModel.Email)).Returns(MembershipCreateStatus.Success);
            _repoMembership.Setup(x => x.getUserID(facultyVM.registerModel.UserName)).Returns(facultyVM.facultyMember.UniqueID);
            _repoMembership.Setup(x => x.addUserToRole(facultyVM.registerModel.UserName, ""));
        }

        [TestMethod]
        public void UnAuthorizedUser_GoesTo_Default()
        {
            var principal = new MockPrincipal(new MockIdentity(""), new string[] { });
            controller.SetFakeControllerContext(principal);
            var result = controller.Index() as RedirectToRouteResult;
            Assert.AreEqual("Default", result.RouteName, "Route name should have been {0}", "Default");
        }

        [TestMethod]
        public void Authorized_User_NotIn_Role_GoesTo_Default()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "BadRole" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Index() as RedirectToRouteResult;
            Assert.AreEqual("Default", result.RouteName, "Route name should have been {0}", "Default");
        }

        [TestMethod]
        public void Authorized_User_InRole_GoesTo_Index()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "Admin" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Index() as ViewResult;
            Assert.AreEqual("Index", result.ViewName, "Route name should have been {0}", "Index");
        }

        [TestMethod]
        public void Admin_Can_View_Create()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "Admin" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Create() as ViewResult;
            Assert.AreEqual("Create", result.ViewName);
        }

        [TestMethod]
        public void NotAdmin_CreateGet_RedirectsTo_Default()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "BadRole" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Create() as RedirectToRouteResult;
            Assert.AreEqual("Default", result.RouteName, "Route name should have been {0}", "Default");
        }

        [TestMethod]
        public void NotAdmin_CreatePost_RedirectsTo_Default()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "BadRole" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Create(facultyVM) as RedirectToRouteResult;
            Assert.AreEqual("Default", result.RouteName, "Route name should have been {0}", "Default");
        }

        [TestMethod]
        public void Admin_RedirectsTo_Student_Default()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "Admin" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Create(facultyVM) as RedirectToRouteResult;
            Assert.AreEqual("Faculty_Default", result.RouteName, "Route name should have been {0}", "Faculty_Default");
        }

        [TestMethod]
        public void Details_GoTo_Details_View()
        {
            var result = controller.Details(facultyMember.UniqueID) as ViewResult;
            Assert.AreEqual("Details", result.ViewName);
            Assert.AreEqual(facultyMember, result.Model);
        }

        [TestMethod]
        public void NotAdmin_DeleteGet_RedirectsTo_Default()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "BadRole" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Delete(facultyMember.UniqueID) as RedirectToRouteResult;
            Assert.AreEqual("Default", result.RouteName, "Route name should have been {0}", "Default");
        }

        [TestMethod]
        public void NotAdmin_DeletePost_RedirectsTo_Default()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "BadRole" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Delete(facultyMember) as RedirectToRouteResult;
            Assert.AreEqual("Default", result.RouteName, "Route name should have been {0}", "Default");
        }

        [TestMethod]
        public void NotAdmin_EditGet_RedirectsTo_Default()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "BadRole" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Edit(facultyMember.UniqueID) as RedirectToRouteResult;
            Assert.AreEqual("Default", result.RouteName, "Route name should have been {0}", "Default");
        }

        [TestMethod]
        public void NotAdmin_EditPost_RedirectsTo_Default()
        {
            var principal = new MockPrincipal(new MockIdentity("Admin"), new string[] { "BadRole" });
            controller.SetFakeControllerContext(principal);
            var result = controller.Edit(facultyMember) as RedirectToRouteResult;
            Assert.AreEqual("Default", result.RouteName, "Route name should have been {0}", "Default");
        }

        [TestMethod]
        public void Authorization_Attributes_Have_Been_Applied()
        {
            var attributes = typeof(HomeController).GetCustomAttributes(typeof(AuthorizeAttribute), true);

            Assert.IsNotNull(attributes);
            Assert.AreEqual(1, attributes.Length);
            var authAttribute = (AuthorizeAttribute)attributes[0];
            string[] roles = authAttribute.Roles.Split(new char[] { ',' });
            Assert.IsTrue(roles.Contains(Constants.Admin));
            Assert.IsTrue(roles.Contains(Constants.OfficeAdmin));
            Assert.IsTrue(roles.Contains(Constants.FacultyMember));
            Assert.IsTrue(roles.Count() == 3);
        }
    }
}
